/**
 * Axios 请求工具配置
 */

import axios, { 
  type AxiosInstance, 
  type AxiosRequestConfig, 
  type AxiosResponse,
  type AxiosError 
} from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
import router from '@/router'
import { useAuthStore } from '@/stores/auth'
import type { ApiResponse, HttpError } from '@/types'

// 创建 axios 实例
const request: AxiosInstance = axios.create({
  baseURL: 'http://localhost:8080/api',
  timeout: 15000,  // 设置15秒超时，语音处理应该在这个时间内完成
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 创建语音处理专用实例，设置更长的超时时间
const voiceRequest: AxiosInstance = axios.create({
  baseURL: 'http://localhost:8080/api',
  timeout: 25000,  // 语音处理设置25秒超时
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// 加载实例
let loadingInstance: any = null
let requestCount = 0

// 显示加载
const showLoading = () => {
  if (requestCount === 0) {
    loadingInstance = ElLoading.service({
      text: '加载中...',
      background: 'rgba(0, 0, 0, 0.7)',
      spinner: 'el-icon-loading'
    })
  }
  requestCount++
}

// 隐藏加载
const hideLoading = () => {
  requestCount--
  if (requestCount <= 0) {
    requestCount = 0
    if (loadingInstance) {
      loadingInstance.close()
      loadingInstance = null
    }
  }
}

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    // 显示加载动画（排除某些不需要加载动画的请求）
    const noLoadingUrls = ['/auth/validate', '/auth/refresh']
    if (!noLoadingUrls.some(url => config.url?.includes(url))) {
      showLoading()
    }

    // 自动添加认证头
    const authStore = useAuthStore()
    const token = authStore.accessToken
    
    if (token && config.headers) {
      config.headers.Authorization = `${authStore.tokenType} ${token}`
    }

    // 添加时间戳防止缓存
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      }
    }

    return config
  },
  (error: AxiosError) => {
    hideLoading()
    ElMessage.error('请求发送失败')
    return Promise.reject(error)
  }
)

// 为语音请求添加拦截器（不使用全局加载遮罩，因为已有进度面板）
voiceRequest.interceptors.request.use(
  (config: any) => {
    // 不显示全局加载遮罩，因为语音处理已有进度面板
    
    // 添加认证头
    const authStore = useAuthStore()
    if (authStore.accessToken) {
      config.headers.Authorization = `Bearer ${authStore.accessToken}`
    }
    
    // 添加时间戳防止缓存
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      }
    }

    return config
  },
  (error: AxiosError) => {
    ElMessage.error('语音请求发送失败')
    return Promise.reject(error)
  }
)

// 语音请求响应拦截器
voiceRequest.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    // 不调用 hideLoading()，因为语音请求不使用全局加载遮罩
    
    const { data } = response
    
    // 检查业务状态码
    const isSuccess = data.success !== undefined ? data.success : (data.code === 200)
    
    if (isSuccess) {
      return response
    } else {
      // 业务错误处理
      ElMessage.error(data.message || '语音处理失败')
      return Promise.reject(new Error(data.message))
    }
  },
  async (error: AxiosError<ApiResponse>) => {
    // 不调用 hideLoading()，因为语音请求不使用全局加载遮罩
    
    const { response, message } = error
    
    if (response) {
      const { status, data } = response
      
      switch (status) {
        case 401:
          // Token 过期或无效
          await handleUnauthorized()
          break
        case 403:
          ElMessage.error('没有权限访问语音服务')
          break
        case 404:
          ElMessage.error('语音服务接口不存在')
          break
        case 500:
          ElMessage.error(data?.message || '语音服务内部错误')
          break
        default:
          ElMessage.error(data?.message || `语音处理失败 (${status})`)
      }
    } else if (message.includes('timeout')) {
      ElMessage.error('语音处理超时，请重试')
    } else {
      ElMessage.error('语音处理网络错误')
    }
    
    return Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    hideLoading()
    
    const { data } = response
    
    // 检查业务状态码
    // 兼容不同的响应格式：有些接口返回success字段，有些只返回code
    const isSuccess = data.success !== undefined ? data.success : (data.code === 200)
    
    if (isSuccess) {
      return response
    } else {
      // 业务错误处理
      ElMessage.error(data.message || '操作失败')
      return Promise.reject(new Error(data.message))
    }
  },
  async (error: AxiosError<ApiResponse>) => {
    hideLoading()
    
    const { response, message } = error
    
    if (response) {
      const { status, data } = response
      
      switch (status) {
        case 401:
          // Token 过期或无效
          await handleUnauthorized()
          break
        case 403:
          ElMessage.error('没有权限访问该资源')
          break
        case 404:
          ElMessage.error('请求的资源不存在')
          break
        case 422:
          // 表单验证错误
          if (data?.message) {
            ElMessage.error(data.message)
          } else {
            ElMessage.error('请求参数有误')
          }
          break
        case 429:
          ElMessage.error('请求过于频繁，请稍后再试')
          break
        case 500:
          ElMessage.error('服务器内部错误')
          break
        case 502:
        case 503:
        case 504:
          ElMessage.error('服务暂时不可用，请稍后再试')
          break
        default:
          ElMessage.error(data?.message || `请求失败 (${status})`)
      }
    } else if (message.includes('timeout')) {
      ElMessage.error('请求超时，请检查网络连接')
    } else if (message.includes('Network Error')) {
      ElMessage.error('网络连接错误，请检查网络')
    } else {
      ElMessage.error('请求失败，请稍后再试')
    }
    
    return Promise.reject(createHttpError(error))
  }
)

// 处理 401 未授权错误
const handleUnauthorized = async () => {
  const authStore = useAuthStore()
  
  try {
    // 尝试刷新 token
    await authStore.refreshTokenAction()
  } catch (refreshError) {
    // 刷新失败，清除认证信息并跳转到登录页
    authStore.logout()
    ElMessage.error('登录已过期，请重新登录')
    
    // 跳转到登录页，保存当前路由用于登录后跳转
    const currentRoute = router.currentRoute.value
    if (currentRoute.path !== '/login') {
      router.push({
        path: '/login',
        query: { redirect: currentRoute.fullPath }
      })
    }
  }
}

// 创建 HTTP 错误对象
const createHttpError = (error: AxiosError<ApiResponse>): HttpError => {
  const { response } = error
  
  return {
    code: response?.status || 0,
    message: response?.data?.message || error.message || '未知错误',
    details: response?.data
  }
}

// 导出请求方法
export const http = {
  get: <T = any>(url: string, config?: AxiosRequestConfig): Promise<T> => {
    return request.get<ApiResponse<T>>(url, config).then(res => res.data.data)
  },
  
  post: <T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {
    return request.post<ApiResponse<T>>(url, data, config).then(res => res.data.data)
  },
  
  put: <T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {
    return request.put<ApiResponse<T>>(url, data, config).then(res => res.data.data)
  },
  
  delete: <T = any>(url: string, config?: AxiosRequestConfig): Promise<T> => {
    return request.delete<ApiResponse<T>>(url, config).then(res => res.data.data)
  },
  
  patch: <T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> => {
    return request.patch<ApiResponse<T>>(url, data, config).then(res => res.data.data)
  }
}

// 上传文件专用方法
export const upload = (url: string, formData: FormData, onProgress?: (progress: number) => void) => {
  return request.post(url, formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: (progressEvent) => {
      if (onProgress && progressEvent.total) {
        const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        onProgress(progress)
      }
    }
  })
}

export default request
export { voiceRequest }
